package study.datastructure.graph.criticalpath;/**
 * @program: datastructure
 * @author: lcy
 * @create: 2024-06-18 13:19
 */

import java.util.*;

/**
 2024/6/18,
 */


public class Project {

    List<Task> tasks;

    public Project(){
        this.tasks=new ArrayList<>();
    }

    public void addTask(Task task){
        this.tasks.add(task);
    }

    public void calculateCriticalPathMethod(){
        Map<Task,Integer> inDegree=new HashMap<>();

        //初始化入度为0
        for (Task task : tasks) {
            inDegree.put(task,0);
        }

        for (Task task : tasks) {
            for (Task predecessor : task.predecessors) {
                inDegree.put(task,inDegree.get(task)+1);
            }
        }

        Queue<Task> queue=new LinkedList<>();
        for (Task task : tasks) {
            if (inDegree.get(task)==0) {
                queue.add(task);
            }
        }

        while (!queue.isEmpty()){
            Task currentTask = queue.poll();
            for (Task task : tasks) {
                if (task.predecessors.contains(currentTask)) {
                    task.earliestStart=Math.max(currentTask.earliestFinish,task.earliestStart);
                    task.earliestFinish= task.earliestStart+ task.duration;
                }

                inDegree.put(task,inDegree.get(task)-1);

                if (inDegree.get(task)==0){
                    queue.add(task);
                }
            }
        }

        //定义项目的持续时间
        int projectDuration=0;
        for (Task task : tasks) {
            projectDuration=Math.max(task.earliestFinish,projectDuration);
        }
        //初始化最晚完成时间
        for (Task task : tasks) {
            task.latestFinish=projectDuration;
        }

        for (int i=tasks.size()-1;i>=0;i--){
            Task currentTask = tasks.get(i);
            for (Task task : tasks) {
                if (task.predecessors.contains(currentTask)){
                    currentTask.latestFinish=Math.min(currentTask.latestFinish,task.latestStart);
                }
            }
            currentTask.latestStart=currentTask.latestFinish- currentTask.duration;
        }
        System.out.println("System out Critical Path:");
        for (Task task : tasks) {
            if (task.earliestStart==task.latestStart){
                System.out.println(task.name);
            }
        }
        //debug
        for (Task task : tasks) {
            System.out.println(task);
        }

    }



}
